// #include "TcpClient.hpp"
// #include <iostream>
// #include <sys/socket.h>
// #include <sys/types.h>
// #include <netinet/in.h>
// #include <arpa/inet.h>
// #include <memory.h>
// #include "Log.hpp"
// #include "Common.hpp"

// using namespace LogModule;
// //./client_tcp server_ip server_port
// int main(int argc, char *argv[])
// {
//     if (argc != 3)
//     {
//         std::cout << "Usage:./client_tcp server_ip server_port" << std::endl;
//         return 1;
//     }
//     std::string server_ip = argv[1];
//     uint16_t server_port = std::stoi(argv[2]);
//     int sockfd = socket(AF_INET, SOCK_STREAM, 0);
//     if (sockfd < 0)
//     {
//         LOG(LogLevel::FATAL) << "socket error";
//         return 2;
//     }
//     // client不需要显示的bind和listen，这部分有OS自动进行
//     // 不能用recvfrom和sendto，因为他们不是面向连接的，而是面向无连接的
//     // 先建立连接，然后再进行通信，使用connect时OS就会自动bind
//     struct sockaddr_in server_addr;
//     memset(&server_addr, 0, sizeof server_addr);
//     server_addr.sin_family = AF_INET;
//     server_addr.sin_addr.s_addr = inet_addr(server_ip.c_str());
//     server_addr.sin_port = htons(server_port);
//     int n = connect(sockfd, CONV(&server_addr), sizeof server_addr);
//     if (n < 0)
//     {
//         LOG(LogLevel::FATAL) << "connect error";
//         return 3;
//     }
//     while(true)
//     {
//         char buff[4096] = {0};
//         std::cout<<"Please input message to send:";
//         std::string message;
//         std::getline(std::cin, message);
//         int n=write(sockfd, message.c_str(),message.size());
//         if(n=0)
//         {
//             std::cout<<"我输入好了"<<std::endl;
//             std::cout<< n <<std::endl;

//             int m= read(sockfd, buff,sizeof buff - 1);
//             //std::cout<<"********"<<std::endl;
//             if(m>=0)
//             {
//                 buff[m]=0;
//                 std::cout<<"Received message:"<<buff<<std::endl;
//             }
//             else
//             {
//                 LOG(LogLevel::ERROR)<<"Read error";
//                 break;
//             }
//         }
//         else if (n== 0)
//         {
//             continue;
//         }
//         else
//         {
//             LOG(LogLevel::ERROR)<<"Write error";
//             break;
//         }

//     }
//     close(sockfd);
// }

#include "Protocol.hpp"
#include "TcpClient.hpp"
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <memory.h>
#include "Log.hpp"
#include "Common.hpp"
#include "Calculator.hpp"

using namespace LogModule;
//./client_tcp server_ip server_port
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cout << "Usage:./client_tcp server_ip server_port" << std::endl;
        return 1;
    }
    std::string server_ip = argv[1];
    uint16_t server_port = std::stoi(argv[2]);
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        LOG(LogLevel::FATAL) << "socket error";
        return 2;
    }
    // client不需要显示的bind和listen，这部分有OS自动进行
    // 不能用recvfrom和sendto，因为他们不是面向连接的，而是面向无连接的
    // 先建立连接，然后再进行通信，使用connect时OS就会自动bind
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof server_addr);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(server_ip.c_str());
    server_addr.sin_port = htons(server_port);
    int n = connect(sockfd, CONV(&server_addr), sizeof server_addr);
    if (n < 0)
    {
        LOG(LogLevel::FATAL) << "connect error";
        return 3;
    }
    while (true)
    {

        int x, y;
        char op;
        std::cout << "输入x" << std::endl;
        std::cin >> x;
        std::cout << "输入y" << std::endl;
        std::cin >> y;

        std::cout << "输入op" << std::endl;
        std::cin >> op;
        Request req(x, y, op);
        // 序列化
        std::string message;
        req.Serialize(message);
        // Encode
        Encode(message);
        // 发送
        char buff[4096] = {0};;
        // std::string message;
        // std::getline(std::cin, message);
        int n = write(sockfd, message.c_str(), message.size());
        if (n > 0) // 这里要特别注意，如果write什么都没读取到，不可以把消息发给服务端，会直接卡住服务端的read，进而卡死客户端的read,所以要if（n==0）则重新输入
        {
            std::cout << "我输入好了" << std::endl;
            int m = read(sockfd, buff, sizeof buff - 1);
            if (m >= 0)
            {
                buff[m] = 0;
                //读取回答
                std::string package=buff;
                std::string res_str;
                Decode(package,&res_str);
                //反序列化
                Response res;
                res.Deserialize(res_str);
                //
                std::cout << "Received result:" << res.Result() << std::endl;
                std::cout << "Received error_code:" << res.ErrorCode() << std::endl;
            }
            else
            {
                LOG(LogLevel::ERROR) << "Read error";
                break;
            }
        }
        else if (n == 0)
        {
            continue;
        }
        else
        {
            LOG(LogLevel::ERROR) << "Write error";
            break;
        }
    }
    close(sockfd);
}